/*
 UploadiFive 1.2.3
 Copyright (c) 2012 Reactive Apps, Ronnie Garcia
 Released under the MIT License
 */
;(function ($) {
    let methods = {
        init: function (options) {
            return this.each(function () {
                // 创建一个jQuery DOM对象的引用
                let $this = $(this);
                $this.data('uploadifive', {
                    inputs: {}, // 包含所有文件的对象
                    inputCount: 0,  // 创建的文件总数
                    fileID: 0,
                    queue: {
                        count: 0, // 队列中的文件总数
                        selected: 0, // 最后一次选择操作中选择的文件数
                        replaced: 0, // 最后一次选择操作中替换的文件数
                        errors: 0, // 最后一次选择操作中返回错误的文件数
                        queued: 0, // 最后一次选择操作中添加到队列的文件数
                        cancelled: 0  // 已取消或从队列中删除的文件总数
                    },
                    uploads: {
                        current: 0, // 当前上载的文件数
                        attempts: 0, // 最后一次上载操作中尝试的文件上载数
                        successful: 0, // 最后一次上载操作中成功上载的文件数
                        errors: 0, // 最后一次上载操作中返回错误的文件数
                        count: 0  // 成功上载的文件总数
                    }
                });
                let $data = $this.data('uploadifive');
                // 设置默认选项
                let settings = $data.settings = $.extend({
                    auto: true,               // 将文件添加到队列时自动上载文件
                    buttonClass: false,              // 要添加到UploadiLive按钮的样式类
                    buttonText: 'Select Files',     // “上传”按钮上显示的文本
                    checkScript: false,              // 检查现有文件名的脚本的路径
                    dnd: true,               // 是否允许拖放到队列中
                    dropTarget: false,              // 放置目标的选择器
                    fileObjName: 'Filedata',         // 服务器端脚本中使用的文件对象的名称
                    fileSizeLimit: 0,                  // 允许上载的最大文件大小
                    fileType: false,              // 允许的文件扩展名，用逗号字符分隔
                    formData: {},                 // 要发送到服务端的其他数据
                    height: 30,                 // 按钮的高度
                    itemTemplate: false,              // 队列中项目的HTML标记
                    method: 'post',             // 提交上载时使用的方式
                    multi: false,              // 是否允许选择多个文件
                    overrideEvents: [],                 // 要覆盖的事件数组
                    queueID: false,              // 队列标签ID
                    queueSizeLimit: 0,                  // 队列中可包含的最大文件数
                    removeCompleted: false,              // 上载完成后是否删除
                    simUploadLimit: 0,                  // 一次上载的最大文件数
                    truncateLength: 0,                  // 文件名的长度限制
                    uploadLimit: 0,                  // 上载的最大文件数
                    uploadScript: 'uploadifive.php',  // 上载脚本的路径
                    width: 100                 // 按钮的宽度
                    /*
                     // Events
                     onAddQueueItem   : function(file) {},                        // 文件添加到队列时触发
                     onCancel         : function(file) {},                        // 当文件被取消或从队列中删除时触发
                     onCheck          : function(file, exists) {},                // 检查服务器是否存在现有文件时触发
                     onClearQueue     : function(queue) {},                       // 清空队列时触发
                     onDestroy        : function() {}                             // 销毁时触发
                     onDrop           : function(files, numberOfFilesDropped) {}, // 将文件拖入队列时触发
                     onError          : function(file, fileType, data) {},        // 发生错误时触发
                     onFallback       : function() {},                            // 如果浏览器不支持HTML5文件API，则触发
                     onInit           : function() {},                            // 初始化时触发
                     onQueueComplete  : function() {},                            // 上传队列完成时触发一次
                     onProgress       : function(file, event) {},                 // 在每次上传进度更新时触发
                     onSelect         : function() {},                            // 选择文件时触发一次
                     onUpload         : function(file) {},                        // 启动上载队列时触发
                     onUploadComplete : function(file, data) {},                  // 上载文件成功时触发
                     onUploadFile     : function(file) {},                        // 为每个上传的文件触发
                     */
                }, options);
                // 创建文件类型数组
                let file_types;
                if (settings.fileType) {
                    file_types = settings.fileType.split(',');
                }
                // 计算文件大小限制
                if (isNaN(settings.fileSizeLimit)) {
                    let fileSizeLimitBytes = parseInt(settings.fileSizeLimit) * 1.024;
                    let $fileSizeLimit = settings.fileSizeLimit;
                    if ($fileSizeLimit.indexOf('KB') > -1) {
                        settings.fileSizeLimit = fileSizeLimitBytes * 1000;
                    } else if ($fileSizeLimit.indexOf('MB') > -1) {
                        settings.fileSizeLimit = fileSizeLimitBytes * 1000000;
                    } else if ($fileSizeLimit.indexOf('GB') > -1) {
                        settings.fileSizeLimit = fileSizeLimitBytes * 1000000000;
                    }
                } else {
                    settings.fileSizeLimit = settings.fileSizeLimit * 1024;
                }
                // 创建上传文件模板
                $data.inputTemplate = $('<input type="file">').css({'font-size': settings.height + 'px', 'opacity': 0, 'position': 'absolute', 'right': '-3px', 'top': '-3px', 'z-index': 999});
                // 创建新输入框
                $data.createInput = function () {
                    // 克隆上传的文件
                    let input = $data.inputTemplate.clone();
                    // 为输入框命唯一名称
                    let inputName = input.name = 'input' + $data.inputCount++;
                    // 设置是否可多选
                    if (settings.multi) {
                        input.attr('multiple', true);
                    }
                    // 设置允许上传的类型
                    if (settings.fileType) {
                        input.attr('accept', settings.fileType);
                    }
                    // 设置 onchange 事件
                    input.bind('change', function () {
                        $data.queue.selected = 0;
                        $data.queue.replaced = 0;
                        $data.queue.errors = 0;
                        $data.queue.queued = 0;
                        // 将要上传的文件加入队列
                        let limit = this.files.length;
                        $data.queue.selected = limit;
                        if ($data.queue.count + limit > settings.queueSizeLimit && settings.queueSizeLimit !== 0) {
                            if ($.inArray('onError', settings.overrideEvents) < 0) {
                                alert('The maximum number of queue items has been reached (' + settings.queueSizeLimit + ').  Please select fewer files.');
                            }
                            //  触发错误事件
                            if (typeof settings.onError === 'function') {
                                settings.onError.call($this, 'QUEUE_LIMIT_EXCEEDED');
                            }
                        } else {
                            for (let n = 0; n < limit; n++) {
                                let file = this.files[n];
                                $data.addQueueItem(file);
                            }
                            $data.inputs[inputName] = this;
                            $data.createInput();
                        }
                        // 如果启用自动上载，则上载文件
                        if (settings.auto) {
                            methods.upload.call($this);
                        }
                        // 触发选择事件
                        if (typeof settings.onSelect === 'function') {
                            settings.onSelect.call($this, $data.queue);
                        }
                    });
                    // 隐藏当前项并添加新项
                    if ($data.currentInput) {
                        $data.currentInput.hide();
                    }
                    $data.button.append(input);
                    $data.currentInput = input;
                };
                // 移除输入框
                $data.destroyInput = function (key) {
                    $($data.inputs[key]).remove();
                    delete $data.inputs[key];
                    $data.inputCount--;
                };
                // 将文件拖入队列
                $data.drop = function (e) {
                    // Stop FireFox from opening the dropped file(s)
                    e.preventDefault();
                    e.stopPropagation();
                    $data.queue.selected = 0;
                    $data.queue.replaced = 0;
                    $data.queue.errors = 0;
                    $data.queue.queued = 0;
                    let fileData = e.dataTransfer;
                    let inputName = fileData.name = 'input' + $data.inputCount++;
                    // 将文件加入队列
                    let limit = fileData.files.length;
                    $data.queue.selected = limit;
                    if (($data.queue.count + limit) > settings.queueSizeLimit && settings.queueSizeLimit !== 0) {
                        // 检查是否超过队列限制
                        if ($.inArray('onError', settings.overrideEvents) < 0) {
                            alert('The maximum number of queue items has been reached (' + settings.queueSizeLimit + ').  Please select fewer files.');
                        }
                        // 触发错误事件
                        if (typeof settings.onError === 'function') {
                            settings.onError.call($this, 'QUEUE_LIMIT_EXCEEDED');
                        }
                    } else {
                        // 将文件加入队列
                        for (let n = 0; n < limit; n++) {
                            let file = fileData.files[n];
                            $data.addQueueItem(file);
                            // 检查文件类型
                            if (file_types) {
                                if (file_types.indexOf(file.name.substring(file.name.lastIndexOf('.'))) < 0) {
                                    $data.error('FORBIDDEN_FILE_TYPE', file);
                                }
                            }
                        }
                        // 将数据保存到输入框
                        $data.inputs[inputName] = fileData;
                    }
                    // 如果启用自动上载，则上载文件
                    if (settings.auto) {
                        methods.upload.call($this);
                    }
                    // 触发拖拽事件
                    if (typeof settings.onDrop === 'function') {
                        settings.onDrop.call($this, fileData.files, fileData.files.length);
                    }
                };
                // 检查文件名是否已存在于队列
                $data.fileExistsInQueue = function (file) {
                    for (let key in $data.inputs) {
                        let input = $data.inputs[key];
                        let limit = input.files.length;
                        for (let n = 0; n < limit; n++) {
                            let existingFile = input.files[n];
                            // 检查文件名是否匹配
                            if (existingFile.name === file.name && !existingFile.complete) {
                                return true;
                            }
                        }
                    }
                    return false;
                };
                // 从队列中移除一个文件
                $data.removeExistingFile = function (file) {
                    for (let key in $data.inputs) {
                        let input = $data.inputs[key];
                        let limit = input.files.length;
                        for (let n = 0; n < limit; n++) {
                            let existingFile = input.files[n];
                            // 检查文件名是否匹配
                            if (existingFile.name === file.name && !existingFile.complete) {
                                $data.queue.replaced++;
                                methods.cancel.call($this, existingFile, true);
                            }
                        }
                    }
                };
                // 创建文件模板
                if (settings.itemTemplate === false) {
                    $data.queueItem = $('<div class="uploadifive-queue-item">' +
                        '<a class="close" href="#">X</a>' +
                        '<div><span class="filename"></span><span class="fileinfo"></span></div>' +
                        '<div class="progress">' +
                        '<div class="progress-bar"></div>' +
                        '</div>' +
                        '</div>');
                } else {
                    $data.queueItem = $(settings.itemTemplate);
                }
                // 加入队列
                $data.addQueueItem = function (file) {
                    if ($.inArray('onAddQueueItem', settings.overrideEvents) < 0) {
                        // 查检文件名是否已存在于队列中
                        $data.removeExistingFile(file);
                        // 克隆一个队列
                        file.queueItem = $data.queueItem.clone();
                        // 为队列添加ID
                        file.queueItem.attr('id', settings.id + '-file-' + $data.fileID++);
                        // 为关闭按钮绑定事件
                        file.queueItem.find('.close').bind('click', function () {
                            methods.cancel.call($this, file);
                            return false;
                        });
                        let fileName = file.name;
                        //if (fileName.length > settings.truncateLength && settings.truncateLength !== 0) {
                        //    fileName = fileName.substring(0, settings.truncateLength) + '...';
                        //}
                        let $reader = new FileReader();
                        $reader.onload = function ($evt) {
                            file.queueItem.find('.filename').html('<img src="' + $evt.target.result + '" style="min-width: 50px;min-height: 50px;max-width: 100px;max-height: 100px;">').attr('title', fileName);
                        }
                        $reader.readAsDataURL(file)
                        // file.queueItem.find('.filename').html(fileName)
                        // 添加对文件的引用
                        file.queueItem.data('file', file);
                        $data.queueEl.append(file.queueItem);
                    }
                    // 触发添加队列事件
                    if (typeof settings.onAddQueueItem === 'function') {
                        settings.onAddQueueItem.call($this, file);
                    }
                    // 检查文件类型
                    if (file_types) {
                        if (file_types.indexOf(file.name.substring(file.name.lastIndexOf('.'))) < 0) {
                            $data.error('FORBIDDEN_FILE_TYPE', file);
                        }
                    }
                    // 检查文件大小
                    if (file.size > settings.fileSizeLimit && settings.fileSizeLimit !== 0) {
                        $data.error('FILE_SIZE_LIMIT_EXCEEDED', file);
                    } else {
                        $data.queue.queued++;
                        $data.queue.count++;
                    }
                };
                // 从队列移除一项
                $data.removeQueueItem = function (file, instant, delay) {
                    // 设置默认延迟
                    if (!delay) {
                        delay = 0;
                    }
                    let fadeTime = instant ? 0 : 500;
                    if (file.queueItem) {
                        if (file.queueItem.find('.fileinfo').html() !== ' - Completed') {
                            file.queueItem.find('.fileinfo').html(' - Cancelled');
                        }
                        file.queueItem.find('.progress-bar').width(0);
                        file.queueItem.delay(delay).fadeOut(fadeTime, function () {
                            $(this).remove();
                        });
                        delete file.queueItem;
                        $data.queue.count--;
                    }
                };
                // 计算需要上传的文件数
                $data.filesToUpload = function () {
                    let filesToUpload = 0;
                    for (let key in $data.inputs) {
                        let input = $data.inputs[key];
                        let limit = input.files.length;
                        for (let n = 0; n < limit; n++) {
                            let file = input.files[n];
                            if (!file.skip && !file.complete) {
                                filesToUpload++;
                            }
                        }
                    }
                    return filesToUpload;
                };
                // 检查文件是否已存在
                $data.checkExists = function (file) {
                    if ($.inArray('onCheck', settings.overrideEvents) < 0) {
                        // 此请求需要同步
                        $.ajaxSetup({
                            'async': false
                        });
                        // 检测文件
                        let checkData = $.extend(settings.formData, {filename: file.name});
                        $.post(settings.checkScript, checkData, function (fileExists) {
                            file.exists = parseInt(fileExists);
                        });
                        if (file.exists) {
                            if (!confirm('A file named ' + file.name + ' already exists in the upload folder.\nWould you like to replace it?')) {
                                // 如果不允许更改文件名，则取消上载
                                methods.cancel.call($this, file);
                                return true;
                            }
                        }
                    }
                    // 触发检查事件
                    if (typeof settings.onCheck === 'function') {
                        settings.onCheck.call($this, file, file.exists);
                    }
                    return false;
                };
                // 上载一个文件
                $data.uploadFile = function (file, uploadAll) {
                    if (!file.skip && !file.complete && !file.uploading) {
                        file.uploading = true;
                        $data.uploads.current++;
                        $data.uploads.attempted++;
                        // 创建一个 ajax 请求
                        let xhr = file.xhr = new XMLHttpRequest();
                        // 开始上载
                        // Use the faster FormData if it exists
                        if (typeof FormData === 'function' || typeof FormData === 'object') {
                            // 创建一个新的表单数据对象
                            let formData = new FormData();
                            // 加入表单数据
                            formData.append(settings.fileObjName, file);
                            // 添加其它表单数据
                            for (let i in settings.formData) {
                                formData.append(i, settings.formData[i]);
                            }
                            //  打开AJAX调用
                            xhr.open(settings.method, settings.uploadScript, true);
                            // 进度函数
                            xhr.upload.addEventListener('progress', function (e) {
                                if (e.lengthComputable) {
                                    $data.progress(e, file);
                                }
                            }, false);
                            // 完成函数
                            xhr.addEventListener('load', function (e) {
                                if (this.readyState === 4) {
                                    file.uploading = false;
                                    if (this.status === 200) {
                                        if (file.xhr.responseText !== 'Invalid file type.') {
                                            $data.uploadComplete(e, file, uploadAll);
                                        } else {
                                            $data.error(file.xhr.responseText, file, uploadAll);
                                        }
                                    } else if (this.status === 404) {
                                        $data.error('404_FILE_NOT_FOUND', file, uploadAll);
                                    } else if (this.status === 403) {
                                        $data.error('403_FORBIDDEN', file, uploadAll);
                                    } else {
                                        $data.error('Unknown Error', file, uploadAll);
                                    }
                                }
                            });
                            // Send the form data (multipart/form-data)
                            xhr.send(formData);
                        } else {
                            // Send as binary
                            let reader = new FileReader();
                            reader.onload = function (e) {
                                //  设置一些文件生成器变量
                                let boundary = '-------------------------' + (new Date()).getTime(),
                                    dashes = '--',
                                    eol = '\r\n',
                                    binFile = '';
                                // Build an RFC2388 String
                                binFile += dashes + boundary + eol;
                                // 生成头参数
                                binFile += 'Content-Disposition: form-data; name="' + settings.fileObjName + '"';
                                if (file.name) {
                                    binFile += '; filename="' + file.name + '"';
                                }
                                binFile += eol;
                                binFile += 'Content-Type: application/octet-stream' + eol + eol;
                                binFile += e.target.result + eol;
                                for (let key in settings.formData) {
                                    binFile += dashes + boundary + eol;
                                    binFile += 'Content-Disposition: form-data; name="' + key + '"' + eol + eol;
                                    binFile += settings.formData[key] + eol;
                                }
                                binFile += dashes + boundary + dashes + eol;
                                // 进度函数
                                xhr.upload.addEventListener('progress', function (e) {
                                    $data.progress(e, file);
                                }, false);
                                // 成功函数
                                xhr.addEventListener('load', function (e) {
                                    file.uploading = false;
                                    let status = this.status;
                                    if (status === 404) {
                                        $data.error('404_FILE_NOT_FOUND', file, uploadAll);
                                    } else {
                                        if (file.xhr.responseText !== 'Invalid file type.') {
                                            $data.uploadComplete(e, file, uploadAll);
                                        } else {
                                            $data.error(file.xhr.responseText, file, uploadAll);
                                        }
                                    }
                                }, false);
                                // ajax 请求
                                let url = settings.uploadScript;
                                if (settings.method === 'get') {
                                    let params = $(settings.formData).param();
                                    url += params;
                                }
                                xhr.open(settings.method, url, true);
                                xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
                                // 触发上传事件
                                if (typeof settings.onUploadFile === 'function') {
                                    settings.onUploadFile.call($this, file);
                                }
                                // 上传文件
                                xhr.sendAsBinary(binFile);
                            };
                            reader.readAsBinaryString(file);
                        }
                    }
                };
                // 更新上传进度
                $data.progress = function (e, file) {
                    let percent;
                    if ($.inArray('onProgress', settings.overrideEvents) < 0) {
                        if (e.lengthComputable) {
                            percent = Math.round((e.loaded / e.total) * 100);
                        }
                        file.queueItem.find('.fileinfo').html(' - ' + percent + '%');
                        file.queueItem.find('.progress-bar').css('width', percent + '%');
                    }
                    // 触发改变进度事件
                    if (typeof settings.onProgress === 'function') {
                        settings.onProgress.call($this, file, e);
                    }
                };
                // 触发错误事件
                $data.error = function (errorType, file, uploadAll) {
                    if ($.inArray('onError', settings.overrideEvents) < 0) {
                        let errorMsg;
                        // 获取报错信息
                        switch (errorType) {
                            case '404_FILE_NOT_FOUND':
                                errorMsg = '404 Error';
                                break;
                            case '403_FORBIDDEN':
                                errorMsg = '403 Forbidden';
                                break;
                            case 'FORBIDDEN_FILE_TYPE':
                                errorMsg = 'Forbidden File Type';
                                break;
                            case 'FILE_SIZE_LIMIT_EXCEEDED':
                                errorMsg = 'File Too Large';
                                break;
                            default:
                                errorMsg = 'Unknown Error';
                                break;
                        }
                        // 添加一个错误样式到队列项
                        file.queueItem.addClass('error')
                            // Output the error in the queue item
                            .find('.fileinfo').html(' - ' + errorMsg);
                        // 隐藏进度条
                        file.queueItem.find('.progress').remove();
                    }
                    // 触发报错事件
                    if (typeof settings.onError === 'function') {
                        settings.onError.call($this, errorType, file);
                    }
                    file.skip = true;
                    if (errorType === '404_FILE_NOT_FOUND') {
                        $data.uploads.errors++;
                    } else {
                        $data.queue.errors++;
                    }
                    if (uploadAll) {
                        methods.upload.call($this, null, true);
                    }
                };
                // 触发单个文件上传成功事件
                $data.uploadComplete = function (e, file, uploadAll) {
                    if ($.inArray('onUploadComplete', settings.overrideEvents) < 0) {
                        file.queueItem.find('.progress-bar').css('width', '100%');
                        file.queueItem.find('.fileinfo').html(' - Completed');
                        file.queueItem.find('.progress').slideUp(250);
                        file.queueItem.addClass('complete');
                    }
                    // 触发完成事件
                    if (typeof settings.onUploadComplete === 'function') {
                        settings.onUploadComplete.call($this, file, file.xhr.responseText);
                    }
                    if (settings.removeCompleted) {
                        setTimeout(function () {
                            methods.cancel.call($this, file);
                        }, 3000);
                    }
                    file.complete = true;
                    $data.uploads.successful++;
                    $data.uploads.count++;
                    $data.uploads.current--;
                    delete file.xhr;
                    if (uploadAll) {
                        methods.upload.call($this, null, true);
                    }
                };
                // 触发所有文件上传成功事件
                $data.queueComplete = function () {
                    // 触发队列完成事件
                    if (typeof settings.onQueueComplete === 'function') {
                        settings.onQueueComplete.call($this, $data.uploads);
                    }
                };
                // ----------------------
                // Initialize UploadiFive
                // ----------------------
                // 检查是否允许 H5
                if (window.File && window.FileList && window.Blob && (window.FileReader || window.FormData)) {
                    //  为对象分配一个ID
                    settings.id = 'uploadifive-' + $this.attr('id');
                    // 将输入框放入 div 中并隐藏溢出部分
                    $data.button = $('<div id="' + settings.id + '" class="uploadifive-button">' + settings.buttonText + '</div>');
                    if (settings.buttonClass) {
                        $data.button.addClass(settings.buttonClass);
                    }
                    // 设置按钮样式
                    $data.button.css({
                        'height': settings.height,
                        'line-height': settings.height + 'px',
                        'overflow': 'hidden',
                        'position': 'relative',
                        'display': 'inline-block',
                        'text-align': 'center',
                        'width': settings.width
                    });
                    // 在输入框上方插入按钮
                    $this.before($data.button)
                        // 添加输入框按钮
                        .appendTo($data.button)
                        // 隐藏输入框
                        .hide();
                    // 创建一个新输入框
                    $data.createInput.call($this);
                    // 创建队列容器
                    if (!settings.queueID) {
                        settings.queueID = settings.id + '-queue';
                        $data.queueEl = $('<div id="' + settings.queueID + '" class="uploadifive-queue" />');
                        $data.button.after($data.queueEl);
                    } else {
                        $data.queueEl = $('#' + settings.queueID);
                    }
                    if (!settings.auto) {
                        $data.uploadBtn = $('<input type="button" value="上传">');
                        $data.uploadBtn.css({
                            'height': '30px',
                            'width': '50px',
                            'border-radius': '15px',
                            'border': '1px #ccc solid',
                            'position': 'absolute',
                            'margin-left': '20px'
                        });
                        $data.queueEl.before($data.uploadBtn)
                        $($data.uploadBtn).click(function () {
                            methods.upload.call($this)
                        })
                    }
                    // 添加拖放功能
                    if (settings.dnd) {
                        let $dropTarget = settings.dropTarget ? $(settings.dropTarget) : $data.queueEl.get(0);
                        $dropTarget.addEventListener('dragleave', function (e) {
                            // Stop FireFox from opening the dropped file(s)
                            e.preventDefault();
                            e.stopPropagation();
                        }, false);
                        $dropTarget.addEventListener('dragenter', function (e) {
                            // Stop FireFox from opening the dropped file(s)
                            e.preventDefault();
                            e.stopPropagation();
                        }, false);
                        $dropTarget.addEventListener('dragover', function (e) {
                            // Stop FireFox from opening the dropped file(s)
                            e.preventDefault();
                            e.stopPropagation();
                        }, false);
                        $dropTarget.addEventListener('drop', $data.drop, false);
                    }
                    // Send as binary workaround for Chrome
                    if (!XMLHttpRequest.prototype.sendAsBinary) {
                        XMLHttpRequest.prototype.sendAsBinary = function (datastr) {
                            function byteValue(x) {
                                return x.charCodeAt(0) & 0xff;
                            }

                            let ords = Array.prototype.map.call(datastr, byteValue);
                            let ui8a = new Uint8Array(ords);
                            this.send(ui8a.buffer);
                        };
                    }
                    // 触发初始化事件
                    if (typeof settings.onInit === 'function') {
                        settings.onInit.call($this);
                    }
                } else {
                    //  触发回调事件
                    if (typeof settings.onFallback === 'function') {
                        settings.onFallback.call($this);
                    }
                    return false;
                }
            });
        },
        // Write some data to the console
        debug: function () {
            return this.each(function () {
                console.log($(this).data('uploadifive'));
            });
        },
        // 清空队列
        clearQueue: function () {
            this.each(function () {
                let $this = $(this),
                    $data = $this.data('uploadifive'),
                    settings = $data.settings;
                for (let key in $data.inputs) {
                    let input = $data.inputs[key];
                    let limit = input.files.length;
                    for (let i = 0; i < limit; i++) {
                        let file = input.files[i];
                        methods.cancel.call($this, file);
                    }
                }
                // 触发清空队列事件
                if (typeof settings.onClearQueue === 'function') {
                    settings.onClearQueue.call($this, $('#' + $data.settings.queueID));
                }
            });
        },
        // 取消正在上载的文件或从队列中删除文件
        cancel: function (file, fast) {
            this.each(function () {
                let $this = $(this),
                    $data = $this.data('uploadifive'),
                    settings = $data.settings;
                // 如果用户传递的是队列项ID而不是文件。。。
                if (typeof file === 'string') {
                    let fileID = 0;
                    if (!isNaN(file)) {
                        fileID = 'uploadifive-' + $(this).attr('id') + '-file-' + file;
                    }
                    file = $('#' + fileID).data('file');
                }
                file.skip = true;
                $data.filesCancelled++;
                if (file.uploading) {
                    $data.uploads.current--;
                    file.uploading = false;
                    file.xhr.abort();
                    delete file.xhr;
                    methods.upload.call($this);
                }
                if ($.inArray('onCancel', settings.overrideEvents) < 0) {
                    $data.removeQueueItem(file, fast);
                }
                // 触发取消事件
                if (typeof settings.onCancel === 'function') {
                    settings.onCancel.call($this, file);
                }
            });
        },
        // 上传队列中的文件
        upload: function (file, keeplets) {
            this.each(function () {
                let $this = $(this),
                    $data = $this.data('uploadifive'),
                    settings = $data.settings;
                if (file) {
                    $data.uploadFile.call($this, file);
                } else {
                    // 检查是否达到上传数量限制
                    if ($data.uploads.count + $data.queue.count <= settings.uploadLimit || settings.uploadLimit === 0) {
                        if (!keeplets) {
                            $data.uploads.attempted = 0;
                            $data.uploads.successsful = 0;
                            $data.uploads.errors = 0;
                            let filesToUpload = $data.filesToUpload();
                            // 触发上传事件
                            if (typeof settings.onUpload === 'function') {
                                settings.onUpload.call($this, filesToUpload);
                            }
                        }
                        // 循环浏览文件
                        $('#' + settings.queueID).find('.uploadifive-queue-item').not('.error, .complete').each(function () {
                            let _file = $(this).data('file');
                            // 检查是否达到上传限制
                            if (($data.uploads.current >= settings.simUploadLimit && settings.simUploadLimit !== 0) || ($data.uploads.current >= settings.uploadLimit && settings.uploadLimit !== 0) || ($data.uploads.count >= settings.uploadLimit && settings.uploadLimit !== 0)) {
                                return false;
                            }
                            if (settings.checkScript) {
                                // 遍历已经在处理这个文件
                                _file.checking = true;
                                let skipFile = $data.checkExists(_file);
                                _file.checking = false;
                                if (!skipFile) {
                                    $data.uploadFile(_file, true);
                                }
                            } else {
                                $data.uploadFile(_file, true);
                            }
                        });
                        if ($('#' + settings.queueID).find('.uploadifive-queue-item').not('.error, .complete').size() === 0) {
                            $data.queueComplete();
                        }
                    } else {
                        if ($data.uploads.current === 0) {
                            if ($.inArray('onError', settings.overrideEvents) < 0) {
                                if ($data.filesToUpload() > 0 && settings.uploadLimit !== 0) {
                                    alert('The maximum upload limit has been reached.');
                                    return false
                                }
                            }
                            // 触发报错事件
                            if (typeof settings.onError === 'function') {
                                settings.onError.call($this, 'UPLOAD_LIMIT_EXCEEDED', $data.filesToUpload());
                            }
                        }
                    }
                }
            });
        },
        // 销毁上传插件
        destroy: function () {
            this.each(function () {
                let $this = $(this),
                    $data = $this.data('uploadifive'),
                    settings = $data.settings;
                // 清空队列
                methods.clearQueue.call($this);
                // 如果队列已创建，则销毁
                if (!settings.queueID) {
                    $('#' + settings.queueID).remove();
                }
                // 删除额外输入
                $this.siblings('input').remove();
                //  显示原始文件输入
                $this.show()
                    // 将输入框移出
                    .insertBefore($data.button);
                // 删除按钮
                $data.button.remove();
                // 触发销毁事件
                if (typeof settings.onDestroy === 'function') {
                    settings.onDestroy.call($this);
                }
            });
        }
    };
    $.fn.uploadifive = function (method) {
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
        } else if (typeof method === 'object' || !method) {
            return methods.init.apply(this, arguments);
        } else {
            $.error('The method ' + method + ' does not exist in $.uploadify');
        }
    };
})(jQuery);
